home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / ams__l~1.zoo / util / spr.cc < prev   
Encoding:
C/C++ Source or Header  |  1993-09-05  |  9.2 KB  |  435 lines

  1. //
  2. //  This is a very ugly program, that has had an ugly past.
  3. //
  4. //  It started out as a quick hack in Modula-2 code and was later
  5. //  converted to C++.  One day, I'll rewrite it...
  6. //
  7.  
  8. #include <math.h>
  9. #include <Screen.h>
  10. #include "SmallGraphics.h"
  11. #include <Sprite.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <bool.h>
  15. #include <EasySprite.h>
  16. #include <osbind.h>
  17.  
  18. // NB: Because of a bug currently in g++2.3.3st, I have to assign to these!
  19. static double PI;
  20. static double HALFPI; // This too is to avoid that bug!
  21. //const double PI=3.1415;
  22.  
  23. static double DestinationCentreX;
  24. static double DestinationCentreY;
  25. static double SourceCentreX;
  26. static double SourceCentreY;
  27.  
  28. static int SourceWidth=32;
  29. static int SourceHeight=32;
  30. static double Reduction;
  31.  
  32.  
  33. static int Subdivisions=4;
  34. static inca=0;
  35. static int CurrentFeatures=SP_COLOUR;
  36. static int DestinationWidth=16;
  37. static int DestinationHeight=16;
  38.  
  39. const int SourceX=1;
  40. const int SourceY=1;
  41. static int SourceSpacingX=33;
  42. static int SourceSpacingY=33;
  43. static int SourcesAcross=9;
  44. static int NumRotations=32;
  45.  
  46. static short BackgroundColourIndex;
  47.  
  48. static int CancelProgram=0;
  49. static double xxif,xyif,yxif,yyif;
  50. static Screen *Source, *View, *Desk;
  51.  
  52. static void SetGlobals()
  53. // G++ 2.3.3 is infinite-looping with non-zero double initialisers!
  54. {
  55.     PI=3.1415926536;
  56.     HALFPI=1.5707963268;
  57.     DestinationCentreX=8.0;
  58.     DestinationCentreY=8.0;
  59.     SourceCentreX=16.0;
  60.     SourceCentreY=16.0;
  61.     Reduction=2.0;
  62. }
  63.  
  64. double Trunc(double x) { return (double)(int)x; }
  65.  
  66. void Rotate(double angle, double x, double y, double& ToX, double& ToY)
  67. {
  68.     double r,o;
  69.  
  70.     x=x-DestinationCentreX;
  71.     y=y-DestinationCentreY;
  72.     r=sqrt(x*x+y*y);
  73.     if (r<0.000001) {
  74.         o=0.0; // Anything.
  75.     } else {
  76.         o=atan2(y,x)+angle;
  77.     }
  78.  
  79.     ToX=r*cos(o);
  80.     ToY=r*sin(o);
  81. }
  82.  
  83.  
  84. void FindRotatedSource(double angle, double x, double y, double& ToX, double& ToY)
  85. {
  86.     Rotate(angle,x,y,ToX,ToY);
  87.  
  88.     ToX=ToX*Reduction+SourceCentreX;
  89.     ToY=ToY*Reduction+SourceCentreY;
  90. }
  91.  
  92.  
  93. double GreenLevel(short C)
  94. {
  95.     return (double)((C>>4)&7);
  96. }
  97.  
  98. double RedLevel(short C)
  99. {
  100.     return (double)((C>>8)&7);
  101. }
  102.  
  103. double BlueLevel(short C)
  104. {
  105.     return (double)((C>>0)&7);
  106. }
  107.  
  108.  
  109. short ColourSimilarTo(double R, double G, double B, short Except)
  110. {
  111.     short C,Col,BestC;
  112.     double Difference,MinDifference;
  113.  
  114.     MinDifference=HUGE;
  115.     BestC=1;
  116.  
  117.     for (Col=0; Col<16; Col++) if (Col != Except) {
  118.         C=Source->Colour()[Col];
  119.         Difference=fabs(R-RedLevel(C))+fabs(G-GreenLevel(C))+fabs(B-BlueLevel(C));
  120.         if (Difference<MinDifference) {
  121.             MinDifference=Difference;
  122.             BestC=Col;
  123.         }
  124.     }
  125.  
  126.     return BestC;
  127. }
  128.  
  129.  
  130. void CalculateColour(double x, double y, int XX, int YY)
  131. {
  132.     Source->Use();
  133.  
  134.     short C;
  135.     double Red=0.0,Green=0.0,Blue=0.0;
  136.     double fx,fy;
  137.     short X,Y;
  138.  
  139.     short BackgroundColour=C=Source->Colour()[BackgroundColourIndex];
  140.  
  141.     bool NonBackground = FALSE;
  142.  
  143.     for (X=1; X<=Subdivisions; X++) {
  144.         fx=x;
  145.         fy=y;
  146.         for (Y=1; Y<=Subdivisions; Y++) {
  147.             int rfx=int(fx+0.0000001);
  148.             int rfy=int(fy+0.0000001);
  149.  
  150.             if (rfx<0 || rfy<0 || rfx>=SourceWidth || rfy>=SourceHeight) {
  151.                 C=BackgroundColour;
  152.             } else {
  153.                 short CI=ColourAt(XX+rfx,YY+rfy);
  154.                 if (CI==BackgroundColourIndex) {
  155.                     C=BackgroundColour;
  156.                 } else {
  157.                     C=Source->Colour()[CI];
  158.                     NonBackground = TRUE;
  159.                 }
  160.             }
  161.  
  162.             Red=Red+RedLevel(C);
  163.             Green=Green+GreenLevel(C);
  164.             Blue=Blue+BlueLevel(C);
  165.  
  166.             fx=fx+yxif;
  167.             fy=fy+yyif;
  168.         }
  169.         x=x+xxif;
  170.         y=y+xyif;
  171.     }
  172.  
  173.     View->Use();
  174.  
  175.     Red=Red / Subdivisions / Subdivisions;
  176.     Green=Green / Subdivisions / Subdivisions;
  177.     Blue=Blue / Subdivisions / Subdivisions;
  178.  
  179. #ifdef DEBUG
  180.     printf("%lf %lf ",x,y);
  181. #endif
  182.     if (NonBackground) {
  183.         short sim=ColourSimilarTo(Red,Green,Blue,BackgroundColourIndex);
  184.         Colour(sim);
  185. #ifdef DEBUG
  186.         printf("Colour(%d)\n",sim);
  187. #endif
  188.     } else {
  189.         Colour(0);
  190. #ifdef DEBUG
  191.         printf("Background\n");
  192. #endif
  193.     }
  194. }
  195.  
  196. void CalculateSource(short Of, int& x, int& y)
  197. {
  198.     x=SourceX+SourceSpacingX*(Of % SourcesAcross);
  199.     y=SourceY+SourceSpacingY*(Of / SourcesAcross);
  200. }
  201.  
  202. void CreateRotatedIncarnations(short& Pic, Sprite* Sp, double hotx, double hoty)
  203. {
  204.     double xxi,yyi,xyi,yxi;
  205.     double angle;
  206.     int XX,YY;
  207.     double fx,fy,gx,gy;
  208.     double x1,y1,x2,y2,x3,y3;
  209.     short I;
  210.  
  211.     View->Clear();
  212.  
  213.     CalculateSource(Pic,XX,YY);
  214.     BackgroundColourIndex=ColourAt(XX,YY);
  215.  
  216.     angle=0.0;
  217.  
  218.     for (I=0; I<NumRotations/4; I++) {
  219.         FindRotatedSource(angle,0.0,0.0,x1,y1);
  220.         FindRotatedSource(angle,1.0,0.0,x2,y2);
  221.         FindRotatedSource(angle,0.0,1.0,x3,y3);
  222.  
  223.         xxi=x2-x1;
  224.         xyi=y2-y1;
  225.         yxi=x3-x1;
  226.         yyi=y3-y1;
  227.         xxif=xxi/Subdivisions;
  228.         xyif=xyi/Subdivisions;
  229.         yxif=yxi/Subdivisions;
  230.         yyif=yyi/Subdivisions;
  231.  
  232.         gx=x1;
  233.         gy=y1;
  234.         for (int x=0; x<DestinationWidth; x++) {
  235.             fx=gx;
  236.             fy=gy;
  237.             for (int y=0; y<DestinationHeight; y++) {
  238. #ifdef DEBUG
  239.                 printf("%lf %lf %d %d\n",fx,fy,x,y);
  240. #endif
  241.                 CalculateColour(fx,fy,XX,YY);
  242.                 Plot(x,y);
  243.                 Plot(DestinationWidth+y,DestinationHeight-1-x);
  244.                 Plot(DestinationWidth*3-1-x,DestinationHeight-1-y);
  245.                 Plot(DestinationWidth*4-1-y,x);
  246.  
  247.                 fx=fx+yxi;
  248.                 fy=fy+yyi;
  249.             }
  250.             gx=gx+xxi;
  251.             gy=gy+xyi;
  252.  
  253.             if (Cconis()) { CancelProgram=1; return; }
  254.         }
  255.  
  256.         for (int X=0; X<4; X++) {
  257.             Rotate(2.0*PI-(angle+X*HALFPI),hotx,hoty,x1,y1);
  258.             Incarnation* Inc=GetIncarnation(*View,X*DestinationWidth,0,DestinationHeight,CurrentFeatures);
  259.             Inc->SetHotSpot(int(x1+DestinationCentreX),int(y1+DestinationCentreY));
  260.             Sp->SetImage(inca+I+(NumRotations/4*X),Inc);
  261.         }
  262.  
  263.         angle=angle+2.0*PI/NumRotations;
  264.     }
  265.     inca+=NumRotations;
  266. }
  267.  
  268.  
  269. void CreateShrunkIncarnation(short Pic, Sprite* Sp, double hotx, double hoty)
  270. {
  271.     double xxi,yyi;
  272.     short x,y;
  273.     double fx,fy,gx;
  274.     int XX,YY;
  275.  
  276.     View->Clear();
  277.  
  278.     CalculateSource(Pic,XX,YY);
  279.     BackgroundColourIndex=ColourAt(XX,YY);
  280.  
  281.     xxi=Reduction;
  282.     yyi=Reduction;
  283.     xxif=xxi/Subdivisions;
  284.     yyif=yyi/Subdivisions;
  285.  
  286.     gx=0;
  287.     for (x=0; x<DestinationWidth; x++) {
  288.         fx=gx;
  289.         fy=0;
  290.         for (y=0; y<DestinationHeight; y++) {
  291.             Source->Use();
  292.             CalculateColour(fx,fy,XX,YY);
  293.             //View->Use();
  294.             Plot(x,y);
  295.             fy=fy+yyi;
  296.         }
  297.         gx=gx+xxi;
  298.  
  299.         if (Cconis()) { CancelProgram=1; return; }
  300.     }
  301.  
  302.     Incarnation* Inc=GetIncarnation(*View,0,0,DestinationHeight,CurrentFeatures);
  303.     Inc->SetHotSpot(int(hotx),int(hoty));
  304.     Sp->SetImage(inca++,Inc);
  305. }
  306.  
  307.  
  308. void CreateDirectIncarnation(short Pic, Sprite* Sp, double hotx, double hoty)
  309. {
  310.     int XX,YY;
  311.     short X,Y,x,y;
  312.  
  313.     CalculateSource(Pic,XX,YY);
  314.     x=XX;
  315.     y=YY;
  316.  
  317.     for (X=0; X<DestinationWidth; X++) {
  318.         for (Y=0; Y<DestinationHeight; Y++) {
  319.             Source->Use();
  320.             Colour(ColourAt(x+X,y+Y));
  321.             View->Use();
  322.             Plot(X,Y);
  323.         }
  324.  
  325.         if (Cconis()) { CancelProgram=1; return; }
  326.     }
  327.  
  328.     Incarnation* Inc=GetIncarnation(*View,0,0,DestinationHeight,CurrentFeatures);
  329.     Inc->SetHotSpot(int(hotx),int(hoty));
  330.     Sp->SetImage(inca++,Inc);
  331. }
  332.  
  333.  
  334. main(int argc, char* argv[])
  335. {
  336.     SetGlobals();
  337.  
  338.     if (argc<3) {
  339.         fprintf(stderr,"Usage: %s cmd {cmd}\n\n",argv[0]);
  340.         fprintf(stderr,"  D SPheight ImgW ImgH        Set dimensions\n");
  341.         fprintf(stderr,"  I imagefile                 Load image file\n");
  342.         fprintf(stderr,"  S savefile                  Set sprite save file\n");
  343.         fprintf(stderr,"  R #rotations                Set # rotations\n");
  344.         fprintf(stderr,"  s #incarnations             New sprite\n");
  345.         fprintf(stderr,"  r from hotx hoty            Add n rotated incas\n");
  346.         fprintf(stderr,"  m from hotx hoty            Add shrunk inca\n");
  347.         fprintf(stderr,"  d from hotx hoty            Add direct inca\n");
  348.         fprintf(stderr,"  a accuracy                  Set pixel subdivision\n");
  349.         fprintf(stderr,"  f features                  Set current features\n");
  350.         fprintf(stderr,"      (w=wide, f=fast)\n");
  351.         exit(1);
  352.     }
  353.  
  354.     InitSmallGraphics();
  355.  
  356.     STLow.Use();
  357.  
  358.     View=new Screen;
  359.     Source=new Screen;
  360.  
  361. #ifdef VISUAL
  362.     View->Show();
  363. #endif
  364.  
  365.     Sprite* Sp=0;
  366.     short Pic;
  367.     double hotx,hoty;
  368.     FILE* fd=0;
  369.  
  370.     for (int arg=1; arg<argc && !CancelProgram; arg++) {
  371.         switch (argv[arg][0]) {
  372.          case 'I':
  373.             Source->Load(argv[++arg]);
  374. #ifdef VISUAL
  375.             Source->ShowPalette();
  376. #endif
  377.         break; case 'D':
  378.             DestinationHeight=atoi(argv[++arg]);
  379.             SourceWidth=atoi(argv[++arg]);
  380.             SourceHeight=atoi(argv[++arg]);
  381.  
  382.             SourceCentreX=SourceWidth/2;
  383.             SourceCentreY=SourceHeight/2;
  384.             DestinationCentreY=DestinationHeight/2;
  385.             Reduction=(double)SourceHeight/DestinationHeight;
  386.             SourceSpacingX=SourceWidth+1;
  387.             SourceSpacingY=SourceHeight+1;
  388.             SourcesAcross=STLow.Width()/SourceSpacingX;
  389.         break; case 'R':
  390.             NumRotations=atoi(argv[++arg]);
  391.         break; case 'S':
  392.             if (fd) fclose(fd);
  393.             fd=fopen(argv[++arg],"wb");
  394.         break; case 's':
  395.             if (Sp && fd) Sp->fput(fd);
  396.             inca=0;
  397.             Sp=new Sprite(atoi(argv[++arg]));
  398.         break; case 'r':
  399.             Pic=atoi(argv[++arg]);
  400.             hotx=atof(argv[++arg]);
  401.             hoty=atof(argv[++arg]);
  402.             CreateRotatedIncarnations(Pic,Sp,hotx,hoty);
  403.         break; case 'm':
  404.             Pic=atoi(argv[++arg]);
  405.             hotx=atof(argv[++arg]);
  406.             hoty=atof(argv[++arg]);
  407.             CreateShrunkIncarnation(Pic,Sp,hotx,hoty);
  408.         break; case 'd':
  409.             Pic=atoi(argv[++arg]);
  410.             hotx=atof(argv[++arg]);
  411.             hoty=atof(argv[++arg]);
  412.             CreateDirectIncarnation(Pic,Sp,hotx,hoty);
  413.         break; case 'a':
  414.             Subdivisions=atoi(argv[++arg]);
  415.         break; case 'f':
  416.             arg++;
  417.             CurrentFeatures=SP_COLOUR;
  418.             DestinationWidth=16;
  419.             for (int c=0; argv[arg][c]; c++) {
  420.                 switch (argv[arg][c]) {
  421.                  case 'w':
  422.                     CurrentFeatures|=SP_WIDE;
  423.                     DestinationWidth=32;
  424.                 break; case 'f':
  425.                     CurrentFeatures|=SP_FAST;
  426.                 }
  427.             }
  428.             DestinationCentreX=DestinationWidth/2;
  429.         }
  430.     }
  431.  
  432.     if (Sp && fd) Sp->fput(fd);
  433.     if (fd) fclose(fd);
  434. }
  435.